//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.erp.exception;


import com.example.erp.domain.DataResult;
import com.example.erp.domain.Status;
import com.example.erp.log.LoggerAppend;
import com.example.erp.log.LoggerType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.concurrent.TimeoutException;

@ControllerAdvice
public class DefaultExceptionHandler {
    private static final Class<?>[] paramException = new Class[]{UnsatisfiedServletRequestParameterException.class, BindException.class, MissingServletRequestParameterException.class, IllegalArgumentException.class};
    public static Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionHandler.class);

    public DefaultExceptionHandler() {
    }

    public static boolean isTimeOutException(Throwable ex) {
        if (TimeoutException.class.isAssignableFrom(ex.getClass())) {
            return true;
        } else {
            return ex.getCause() != null ? isTimeOutException(ex.getCause()) : false;
        }
    }

    public static Status parserExceptionAsStatus(Throwable throwable) {
        if (SystemException.class.isAssignableFrom(throwable.getClass())) {
            SystemException systemException = (SystemException) throwable;
            return new Status(systemException.getErrorCode(), systemException.getErrorReason());
        } else {
            return isTimeOutException(throwable) ? new Status(ErrorCode.TIME_OUT.getErrorCode(), ErrorCode.TIME_OUT.getErrorReason()) : new Status(ErrorCode.OTHER_ERROR.getErrorCode(), ErrorCode.OTHER_ERROR.getErrorReason());
        }
    }

    private void dump_stack(HttpServletRequest request, Throwable tx) {
        String val = request.getParameter("enable_debug");
        if ("true".equals(val)) {
            LOGGER.error("enable.debug.error.stack->", tx);
        }

    }

    @ResponseBody
    @ExceptionHandler({Exception.class})
    public DataResult<Object> defaultErrorHandler(HttpServletRequest request, Exception ex) {
        this.dump_stack(request, ex);
        LoggerAppend append = LoggerAppend.create(request, LoggerType.ERROR);
        String errorCode = ErrorCode.OTHER_ERROR.getErrorCode();
        String errorReason = ErrorCode.OTHER_ERROR.getErrorReason();
        boolean isWriteErrorStack = true;
        if (this.isParamMissing(ex)) {
            errorCode = ErrorCode.PARAM_ERROR.getErrorCode();
            errorReason = ErrorCode.PARAM_ERROR.getErrorReason();
            isWriteErrorStack = false;
        } else if (isTimeOutException(ex)) {
            errorCode = ErrorCode.TIME_OUT.getErrorCode();
            errorReason = ErrorCode.TIME_OUT.getErrorReason();
        }

        this.appendError(append, errorCode, errorReason, request);
        if (isWriteErrorStack) {
            LOGGER.error(append.toString(), ex);
        } else {
            LOGGER.error(append.toString());
        }

        String detailErrorCause = ex.getCause() == null ? "" : ex.getCause().toString();
        if (StringUtils.contains(detailErrorCause, "Load balancer does not have available server for client")) {
            errorReason = errorReason + ":eureka中调用服务不存在或者服务错误";
        }

        return DataResult.faild(errorCode, errorReason);
    }

    @ResponseBody
    @ExceptionHandler({BindException.class})
    public DataResult<Object> bindException(HttpServletRequest request, BindException ex) {
        Iterator var3 = ex.getAllErrors().iterator();

        ObjectError objectError;
        do {
            if (!var3.hasNext()) {
                return DataResult.faild(ErrorCode.PARAM_ERROR);
            }

            objectError = (ObjectError) var3.next();
        } while (!StringUtils.isNotBlank(objectError.getDefaultMessage()));

        return DataResult.faild(ErrorCode.PARAM_ERROR.getErrorCode(), objectError.getDefaultMessage());
    }

    @ResponseBody
    @ExceptionHandler({IllegalArgumentException.class})
    public DataResult<Object> illegalArgumentException(HttpServletRequest request, IllegalArgumentException ex) {
        this.dump_stack(request, ex);
        LoggerAppend append = LoggerAppend.create(request, LoggerType.ERROR);
        String errorCode = ErrorCode.ILLEGAL_ARGUMENT.getErrorCode();
        String errorReason = ErrorCode.ILLEGAL_ARGUMENT.getErrorReason();
        if (StringUtils.isNotBlank(ex.getMessage())) {
            errorReason = errorReason + String.format("(%s)", ex.getMessage());
        }

        this.appendError(append, errorCode, errorReason, request);
        return DataResult.faild(errorCode, errorReason);
    }

    @ResponseBody
    @ExceptionHandler({ErpException.class})
    public DataResult<Object> erpException(ErpException ex) {
        LOGGER.error("catch erpException error code={}， msg={}", ex.getCode(), ex.getMsg());
        return DataResult.faild(ex.getCode(), ex.getMsg());
    }

    private void appendError(LoggerAppend append, String errorCode, String errorReason, HttpServletRequest request) {
        append.append("errorCode", errorCode);
        append.append("errorReason", errorReason);
        request.setAttribute("errorCode", errorCode);
        request.setAttribute("errorReason", errorReason);
    }

    @ResponseBody
    @ExceptionHandler({OpenSystemException.class, SystemException.class})
    public Object systemException(HttpServletRequest request, SystemException ex) {
        this.dump_stack(request, ex);
        LoggerAppend append = LoggerAppend.create(request, LoggerType.ERROR);
        this.appendError(append, ex.getErrorCode(), ex.getErrorReason(), request);
        LOGGER.error(append.toString());
        return DataResult.faild(ex.getErrorCode(), ex.getErrorReason());
    }

    @ResponseBody
    @ExceptionHandler({RpcException.class})
    public Object rpcException(HttpServletRequest request, RpcException ex) {
        this.dump_stack(request, ex);
        LoggerAppend append = LoggerAppend.create(request, LoggerType.ERROR);
        this.appendError(append, ex.getErrorCode(), ex.getErrorReason(), request);
        LOGGER.error(append.toString());
        return DataResult.rpcFaild(ex.getErrorCode(), ex.getErrorReason());
    }

    @ResponseBody
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public DataResult<?> notSupportMethod(HttpServletRequest request, HttpRequestMethodNotSupportedException ex) {
        this.dump_stack(request, ex);
        return DataResult.faild(ErrorCode.NOT_SUPPORT_METHOD);
    }

    private boolean isParamMissing(Exception ex) {
        Class[] var2 = paramException;
        int var3 = var2.length;

        for (int var4 = 0; var4 < var3; ++var4) {
            Class<?> clazz = var2[var4];
            if (ex.getClass() == clazz) {
                return true;
            }
        }

        return false;
    }
}
